program test_cuda_01

  use cudafor

  implicit none

  type(CudaDeviceProp) prop
  integer(cuda_count_kind) free_mem, total_mem
  integer num_devices, dev, cores_per_sm, ierr
  real used_mem_gb, total_mem_gb, free_mem_gb

  ierr = CudaGetDeviceCount(num_devices)
  if (ierr /= CudaSuccess) then
    write(*, *) '[Error]: Failed to get CUDA device number!'
    stop 1
  end if
  write(*, "(' There are ', I0, ' devices.')") num_devices

  do dev = 0, num_devices - 1
    ierr = CudaGetDeviceProperties(prop, dev)
    if (ierr /= CudaSuccess) then
      write(*, *) '[Error]: Failed to get properties of device ', dev, '!'
      stop 1
    end if
    ierr = CudaSetDevice(dev)
    ierr = CudaMemGetInfo(free_mem, total_mem)
    free_mem_gb = real(free_mem) / (1024**3)
    total_mem_gb = real(total_mem) / (1024**3)
    used_mem_gb = total_mem_gb - free_mem_gb

    select case (prop%major)
    case (1)
      cores_per_sm = 8
    case (2)
      cores_per_sm = 32
    case (3)
      cores_per_sm = 192
    case (5)
      cores_per_sm = 128
    case (6)
      cores_per_sm = 128
    case (7)
      cores_per_sm = 64
    case (8)
      cores_per_sm = 128
    case (9)
      cores_per_sm = 128
    case default
      cores_per_sm = 64
    end select

    write(*, "(' -------------------------------------------')")
    write(*, "(' Device: ', I0)") dev
    write(*, "(' Name: ', A)") trim(prop%name)
    write(*, "(' Capacity: ', I0, '.', I0)") prop%major, prop%minor
    write(*, "(' GPU Cores: ', I0)") prop%MultiProcessorCount * cores_per_sm
    write(*, "(' Total memory (GB): ', I0)") int(total_mem_gb)
    write(*, "(' Clock Frequency (GHz): ', F0.2)") real(prop%ClockRate) / 1e6
    write(*, "(' Memory Clock Frequency (GHz): ', F0.2)") real(prop%MemoryClockRate) / 1e6
    write(*, "(' Memory Bus Width (bits): ', I0)") prop%MemoryBusWidth
    write(*, "(' Theory Memory Bandwidth (GB/s): ', F0.2)") 2 * prop%MemoryClockRate * (prop%MemoryBusWidth / 8) / 1.0e6
    write(*, "(' L2 Cache size (MB): ', F0.2)") prop%L2CacheSize / 1.0e6
    write(*, "(' -------------------------------------------')")
  end do

end program test_cuda_01
